#include "main.h"
#include "fm33le0xx_fl.h"
#include "mcu_uart.h"
#include "board_adc.h"
#include "sys_user.h"
#include "k_line.h"
#include "led_side_pwm.h"

mcu_status_t g_mcu_status;            // 与ESP32通讯的内容
motorcycle_info_t g_motorcycle_info;  // ESP32控制自动大灯状态
k_bcm_reply_message_t g_k_reply_data; // 缓存ESP32回复K线的内容
uint8_t g_flasher_faster = 0;         // 1: 双闪快闪，0：双闪慢闪
uint32_t g_k_line_valid_ms = 0;       // k线最后的有效时间
uint32_t flasher_collision_time = 0;  // 双闪冲突静默开始时间

// #define ACC_PIN_GET_VALUE() 0
#define ACC_PIN_GET_VALUE() FL_GPIO_GetInputPin(GPIOA, FL_GPIO_PIN_9)
#define ACC2_PIN_GET_VALUE() FL_GPIO_GetInputPin(GPIOC, FL_GPIO_PIN_6)
#define LIGHT_FLASH_COLSE() FL_GPIO_ResetOutputPin(GPIOA, FL_GPIO_PIN_6)
#define SUN_EN_STATUS(x) (x ? FL_GPIO_SetOutputPin(GPIOD, FL_GPIO_PIN_6) : FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_6))
#define SLEEP_DELAY_TIME 3000

// 大版本号在低位，小版本号在高位
__IO const uint8_t version[3] __attribute__((section(".version"))) = {0x00, 0x0a, 0x0a};

static void headlights_set_level(uint8_t level)
{
    if (level)
    {
        FL_GPIO_SetOutputPin(GPIOB, FL_GPIO_PIN_14);
    }
    else
    {
        FL_GPIO_ResetOutputPin(GPIOB, FL_GPIO_PIN_14);
    }
}

static uint8_t io_get_values()
{
    mcu_status_t status;
    status.io.value = 0x00;
    status.io.raw.light_left = FL_GPIO_GetInputPin(GPIOB, FL_GPIO_PIN_13);
    status.io.raw.light_right = FL_GPIO_GetInputPin(GPIOB, FL_GPIO_PIN_2);
    status.io.raw.light_far = FL_GPIO_GetInputPin(GPIOC, FL_GPIO_PIN_9);
    status.io.raw.light_near = FL_GPIO_GetInputPin(GPIOC, FL_GPIO_PIN_8);
    status.io.raw.light_pos = FL_GPIO_GetInputPin(GPIOB, FL_GPIO_PIN_3);
    status.io.raw.acc = ACC_PIN_GET_VALUE();
    status.io.raw.vcc2 = ACC2_PIN_GET_VALUE();
    return status.io.value;
}

// io经过滤波后输出, 带5ms延迟, 有更新就返回 1，无就返回 0
static uint8_t io_update(mcu_status_t *status)
{
    static uint32_t ticks_ms_last = 0;
    static uint8_t last_value = 0xFF;
    static uint8_t io_values_last = 0x00;

    uint32_t ticks_ms_now = sys_clock_get_ms();
    uint8_t new_value_update = 0;

    if (ticks_ms_now - ticks_ms_last < 5)
    {
        return new_value_update;
    }
    ticks_ms_last = ticks_ms_now;

    // 两次IO读数一致时，更新IO状态
    uint8_t now_value = io_get_values();
    uint8_t same_data = last_value ^ now_value;
    status->io.value = (status->io.value & same_data) | last_value & (~same_data);

    if (io_values_last != status->io.value)
    {
        new_value_update = 1;
    }

    io_values_last = status->io.value;
    last_value = now_value;

    return new_value_update;
}

static uint8_t key_get_values()
{
    mcu_status_t status;
    status.key.up = FL_GPIO_GetInputPin(GPIOA, FL_GPIO_PIN_5);
    status.key.down = FL_GPIO_GetInputPin(GPIOC, FL_GPIO_PIN_1);

    return status.key.value;
}

static uint8_t key_update(mcu_status_t *status)
{
    static uint32_t ticks_ms_last = 0;
    static uint8_t last_value = 0xFF;
    static uint8_t key_values_last = 0x00;

    uint32_t ticks_ms_now = sys_clock_get_ms();
    uint8_t new_value_update = 0;

    if (ticks_ms_now - ticks_ms_last < 5)
    {
        return new_value_update;
    }
    ticks_ms_last = ticks_ms_now;

    // 两次key读数一致时，更新key状态
    uint8_t now_value = key_get_values();
    uint8_t same_data = last_value ^ now_value;
    status->key.value = (status->key.value & same_data) | last_value & (~same_data);

    if (key_values_last != status->key.value)
    {
        user_printf("now values: %x\r\n", status->key.value);
        new_value_update = 1;
    }

    key_values_last = status->key.value;
    last_value = now_value;

    return new_value_update;
}

// 4HZ 用于闪光器翻转
void io_toggle_flash_level_cb(uint32_t time_ms)
{
    static uint8_t times = 0;
    times += 1;

    if (!g_flasher_faster && (times & 0x01))
    {
        return;
    }

    if (flasher_collision_time && sys_clock_get_ms() - flasher_collision_time < 1500)
    {
        FL_GPIO_ResetOutputPin(GPIOA, FL_GPIO_PIN_6);
        return;
    }

    if (g_mcu_status.io.raw.acc == 0)
    {
        FL_GPIO_ToggleOutputPin(GPIOA, FL_GPIO_PIN_6);
    }
    else
    {
        FL_GPIO_ResetOutputPin(GPIOA, FL_GPIO_PIN_6);
    }
}

// 闪光器功率小于一定值时快闪，目前为4.8W，单个灯为4W
void flasher_faster_update()
{
    static uint8_t light_last = 0;
    static uint32_t ticks_count = 0;
    static uint32_t ticks_update_last = 0;

    // 边缘延迟读取电流
    uint8_t light_now = g_mcu_status.io.raw.light_left | g_mcu_status.io.raw.light_right;
    if (light_last != light_now)
    {
        ticks_count = sys_clock_get_ms();
        if (ticks_update_last == 0)
        {
            ticks_update_last = ticks_count;
        }
    }

    uint8_t flasher_faster = 0;
    if (sys_clock_get_ms() - ticks_count < 1000)
    {
        if (sys_clock_get_ms() - ticks_update_last > 800)
        {
            // user_printf("turn dir open, %d \r\n", board_adc_get_led_current());
            if (board_adc_get_flasher_current() < 4000)
            {
                flasher_faster = 1;
            }
        }
        else
        {
            // user_printf("turn dir open wait, %d \r\n", board_adc_get_led_current());
        }
    }
    else
    {
        ticks_update_last = 0;
        // user_printf("turn dir close %d \r\n", board_adc_get_led_current());
    }
    g_flasher_faster = flasher_faster;
}

// 解决闪光器冲突
void flasher_detect_collision()
{
    static uint32_t last_update_time = 0;
    static uint8_t left_last = 0;
    static uint8_t right_last = 0;
    static int8_t times = 0;

    if (sys_clock_get_ms() - last_update_time < 10)
    {
        return;
    }
    last_update_time = sys_clock_get_ms();

    if ((!(FL_GPIO_PIN_6 & GPIOA->DO)) && (g_mcu_status.io.raw.light_right || g_mcu_status.io.raw.light_left))
    {
        times += 1;
        if (times > 15)
        {
            times = 15;
        }
    }
    else
    {
        times -= 1;
        if (times < 0)
        {
            times = 0;
        }
    }

    if (times > 10)
    {
        flasher_collision_time = sys_clock_get_ms();
        return;
    }

    if ((g_mcu_status.io.raw.light_right != right_last || g_mcu_status.io.raw.light_left != left_last) && (!(FL_GPIO_PIN_6 & GPIOA->DO)))
    {
        if (g_mcu_status.io.raw.light_right || g_mcu_status.io.raw.light_left)
        {
            flasher_collision_time = sys_clock_get_ms();
        }
    }

    right_last = g_mcu_status.io.raw.light_right;
    left_last = g_mcu_status.io.raw.light_left;
}

// ESP32消息接收回调
void frame_recv_callback(int cmd, const uint8_t *buf, int len)
{
    if (cmd == CMD_STATUS_TO_FM33 && len == sizeof(motorcycle_info_t))
    {
        memcpy(&g_motorcycle_info, buf, len);
        if (g_motorcycle_info.headlights_enable && g_mcu_status.io.raw.acc == 0)
        {
            headlights_set_level(1);
        }
        else
        {
            headlights_set_level(0);
        }
    }
    else if (cmd == CMD_SEND_TIME_TO_FM33 && len == sizeof(rtc_time_t))
    {
        rtc_time_t rtc_time;
        memcpy(&rtc_time, buf, len);
        sys_clock_set_time(rtc_time.hour, rtc_time.minue, rtc_time.second);
    }
    else if (cmd == CMD_RESET)
    {
        cmd_rsp_t rsp = {
            .error_code = 0,
            .in_boot = 0,
            .reserve = 0,
            .mask = 0,
        };
        mcu_write_bytes(CMD_RESET | 0x8000, (uint8_t *)&rsp, sizeof(cmd_rsp_t));
        sys_clock_delay_ms(5);
        NVIC_SystemReset();
    }
    else if (cmd == CMD_INQUIRY_VERSION)
    {
        cmd_rsp_t rsp = {
            .error_code = 0,
            .in_boot = 0,
            .reserve = 0,
            .mask = 0,
        };
        rsp.mask = (version[0] << 8) | version[1];
        mcu_write_bytes(CMD_INQUIRY_VERSION | 0x8000, (uint8_t *)&rsp, sizeof(cmd_rsp_t));
    }
    else if (cmd == CMD_SEND_COLOR_TO_FM33 && len == sizeof(color_info_t))
    {
        color_info_t color_info;
        memcpy(&color_info, buf, sizeof(color_info_t));
        color_t color = {
            .value = color_info.value,
        };
        if (g_mcu_status.io.raw.acc == 0)
        {
            led_side_fade_to_color(color, 200);
        }
    }
    else if (cmd == CMD_ESP32_TO_K_MSG && len == sizeof(k_bcm_reply_message_t))
    {
        memcpy(&g_k_reply_data, buf, sizeof(k_bcm_reply_message_t));
    }
}

// K线消息接收回调
void k_frame_recv_callback(int cmd, const uint8_t *buf, int len)
{
    // 0x0001
    g_k_line_valid_ms = sys_clock_get_ms();
    if (cmd == 0x10 || cmd == 0x80)
    {
        sys_clock_delay_ms(8);
        k_initial_data_t init_data = {0x0};
        k_line_write_bytes(cmd | 0x08, (uint8_t *)&init_data, sizeof(k_initial_data_t));
    }
    else if (cmd == 0x81)
    {
        mcu_write_bytes(CMD_K_MSG_TO_ESP32, buf, len);
        sys_clock_delay_ms(8);
        k_line_write_bytes(0x89, (uint8_t *)&g_k_reply_data, sizeof(k_bcm_reply_message_t));
    }
}

// bss字段清0
void clear_global_variables()
{
    extern uint32_t Image$$RW_IRAM1$$ZI$$Limit;
    extern uint32_t Image$$RW_IRAM1$$ZI$$Base;
    uint32_t *bss_start = &Image$$RW_IRAM1$$ZI$$Base;
    uint32_t *bss_end = &Image$$RW_IRAM1$$ZI$$Limit;

    // 清零全局未初始化数据段
    for (uint32_t *p = bss_start; p < bss_end; p++)
    {
        *p = 0;
    }
}

int main(void)
{
    clear_global_variables();
    // user_log_init();
    sys_clock_init();
    user_printf("User app load: %d.%d\r\n", version[0], version[1]);

    sys_nvic_init();
    sys_hardware_init();
    FL_Init();

    // 与ESP32通讯
    mcu_uart_init(frame_recv_callback);
    // k线通讯
    k_line_init(k_frame_recv_callback);
    // 光感ADC, 电池电压
    board_adc_init();

    g_mcu_status.time.hour = 0xff;
    g_mcu_status.time.second = 0xff;
    g_mcu_status.time.minute = 0xff;
    if (ACC_PIN_GET_VALUE() == 0 && 1 == g_mcu_status.io.raw.vcc2)
    {
        goto normal_mode;
    }

sleep_mode:
    user_printf("enther sleep mode\r\n");
    led_side_set_status(0);
    sys_clock_disable_it();
    SUN_EN_STATUS(0);
    headlights_set_level(0);
    LIGHT_FLASH_COLSE();
    FL_PMU_SetLowPowerMode(PMU, FL_PMU_POWER_MODE_ACTIVE_OR_LPACTIVE);
    sys_select_rchf_8m_clk();

    for (;;)
    {
        // 如果休眠时有需要回复K线，得切换串口分频系数, 目前没有这个需求
        // k_line_deal_rx_fifo_data();
        io_update(&g_mcu_status);
        // wait acc or nfc wakeup
        if (ACC_PIN_GET_VALUE() == 0 && 1 == ACC2_PIN_GET_VALUE()) // 注意这里不要判断g_mcu_status
        {
            goto normal_mode;
        }
    }

normal_mode:
    user_printf("enther normal mode\r\n");
    // 恢复到正常时钟
    sys_select_rchf_to_pll(32);
    led_side_set_status(1);
    SUN_EN_STATUS(1);
    sys_clock_enable_4hz_cb(io_toggle_flash_level_cb);

    uint32_t time_ms_last = 0;
    uint32_t time_update_io_info = 0;
    uint32_t time_acc_last_ms = sys_clock_get_ms();
    uint8_t wakeup_force_write_info = 1;
    uint8_t rtc_second = 0xff, rtc_hour = 0xff, rtc_minute = 0xff;

    while (1)
    {
        board_update_volt();
        mcu_deal_rx_fifo_data();
        k_line_deal_rx_fifo_data();

        if (sys_clock_get_ms() - time_ms_last >= 200)
        {
            time_ms_last = sys_clock_get_ms();
            flasher_faster_update();
        }

        uint8_t update = 0;
        g_mcu_status.light_value = board_adc_get_light_volt();
        g_mcu_status.bat_small_value = board_adc_get_bat_small_volt();
        if (g_k_line_valid_ms != 0 && sys_clock_get_ms() - g_k_line_valid_ms < 3000)
        {
            g_mcu_status.k_line_valid = 1;
        }
        else
        {
            g_mcu_status.k_line_valid = 0;
        }

        if (sys_clock_get_time(&rtc_hour, &rtc_minute, &rtc_second) == 0)
        {
            g_mcu_status.time.hour = rtc_hour;
            g_mcu_status.time.minute = rtc_minute;
            g_mcu_status.time.second = rtc_second;
        }

        // io 状态改变时，立马上报
        update |= io_update(&g_mcu_status);
        update |= key_update(&g_mcu_status);
        if (update || wakeup_force_write_info || sys_clock_get_ms() - time_update_io_info > 100)
        {
            time_update_io_info = sys_clock_get_ms();
            wakeup_force_write_info = 0;
            mcu_write_bytes(CMD_STATUS_TO_ESP32, (uint8_t *)&g_mcu_status, sizeof(mcu_status_t));
        }

        // acc 检测失效后进入休眠
        if (g_mcu_status.io.raw.acc == 0)
        {
            // 对应工作模式3息屏（到esp处理），4仪表工作
            // acc gpio检测到0为acc有效
            // vcc2 gpio检测到1为vcc2有效
            time_acc_last_ms = sys_clock_get_ms();
        }
        else if (g_mcu_status.io.raw.acc == 1 && (0 == g_mcu_status.io.raw.vcc2 || 1 == g_mcu_status.io.raw.vcc2))
        {
            // 对应工作模式1、2仪表休眠(关机)
            color_t color = {
                .value = 0x00,
            };
            led_side_fade_to_color(color, 0);
        }

        if (sys_clock_get_ms() - time_acc_last_ms > SLEEP_DELAY_TIME)
        {
            user_printf("enter sleep: %d, %d \r\n", sys_clock_get_ms(), time_acc_last_ms);
            goto sleep_mode;
        }

        flasher_detect_collision();
    }
}
